package com.rfsp.common.jwt;

import com.rfsp.common.base.ResultVO;
import com.rfsp.common.feign.OrgFeign;
import com.rfsp.common.feign.PermFeign;
import com.rfsp.common.feign.UserFeign;
import com.rfsp.common.pojo.vo.UserVO;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * token验证拦截
 */
//@Component
public class ShiroInterceptor implements HandlerInterceptor {
	
	public Logger log = LoggerFactory.getLogger(JwtRealm.class);

    @Autowired
    PermFeign permFeign;

    ExecutorService pool =new ThreadPoolExecutor(10,20,1000, TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private OrgFeign orgFeign;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Subject subject = SecurityUtils.getSubject();

        createLog(request);

        String token = request.getHeader(JwtUtil.TOKEN_HEADER);

        String path=request.getServletPath();
        if(!"/my/permiss/".equals(path)){
            //验证用户token是否是库中用户
            if (token != null && !"".equals(token)) {
                Long userId = JwtUtil.getUserId(token);
                ResultVO<UserVO> userResult = new ResultVO<UserVO>("123456");
//                		userFeign.get(apis.getRfcaAppBaseUri(),userId);
                UserVO appUser = userResult.getData();
                if (appUser != null) {
                    if (!appUser.getToken().equals(token)) {
                        //开发临时关闭
                        //throw new ConcurrentAccessException("另一设备已登录");
                    }
                }
            }
        }
        //验证版本
        String version = request.getHeader("version");
        if(version!=null && !"".equals(version)){
            //version="0.1.16";
//            ResultVO<VersionVO> result=versionFeign.getByName(apis.getRfcaAppBaseUri(),version);
//            VersionVO versionVo=result.getVo();
//            if(versionVo==null){
//                throw new VersionPausedException("版本已停用");
//            }
//            if("paused".equals(versionVo.getState())) {
//                throw new VersionPausedException("版本已停用");
//            }
        }

        List<String> excludeList=new ArrayList<String>();
        excludeList.add("/my/auth/checkStatus");
        excludeList.add("/my/auth/login");
        excludeList.add("/my/auth/logout");
        excludeList.add("/my/permiss/");

        //用户状态检测
        if(!excludeList.contains(path)) {
            if (token != null && !"".equals(token)) {
                Long userId = JwtUtil.getUserId(token);
                Long orgId = JwtUtil.getOrgId(token);
//                CheckStatusSDTO sdto = new CheckStatusSDTO();
//                sdto.setUserId(userId);
//                sdto.setOrgId(orgId);
//                ResultVO<ResultVO> userResult = userOrgFeign.checkStatus(sdto);
//                if (ErrorCodes.NOTHING.equals(userResult.getErrorCode())) {
//                    if (ErrorCodes.SENSTIVE_INFO_LOCKED_CODE.equals(userResult.getVo().getErrorCode())) {
//                        throw new ShiroException(userResult.getVo().getTips());
//                    }
//                }
            }
        }

        if(hasPermission(handler)) {
            return true;
        }
        
        return true;
    }


    /**
     * 是否有权限
     *
     * @param handler
     * @return
     */
    private boolean hasPermission(Object handler) {

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            Subject subject = SecurityUtils.getSubject();
            //Long userId = JwtUtil.getUserId(subject.getPrincipals().toString());

            // 获取方法上的注解
            RequiresPermissions requiredPermission = handlerMethod.getMethod().getAnnotation(RequiresPermissions.class);
            // 如果方法上的注解为空 则获取类的注解
            if (requiredPermission == null) {
                requiredPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiresPermissions.class);
            }

            //List<PermissionVO> perms = permFeign.listPermissions(userId);
            if (requiredPermission != null) {
                for (String perm : requiredPermission.value()) {
                    // 如果标记了注解，则判断权限
                    // redis或数据库 中获取该用户的权限信息 并判断是否有权限
                    if (subject.isPermitted(perm)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }




    protected void createLog(HttpServletRequest request){
        pool.execute(new CreateLogRunnable(request));
    }
    private class CreateLogRunnable implements Runnable {
        HttpServletRequest request;
        CreateLogRunnable(HttpServletRequest request){
            this.request=request;
        }
        @Override
        public void run() {
            String token = request.getHeader(JwtUtil.TOKEN_HEADER);
            //JwtUtil.verify(token);
            String url=request.getServletPath();
            if("/error/create".equals(url)){
                return ;
            }
            Long userId=null;
            try {
                userId=JwtUtil.getUserId(token);
            }catch (Exception e){

            }
//            LogDTO dto = new LogDTO();
//            dto.setType("android");
//            dto.setUserId(userId);
//            dto.setUrl(request.getServletPath());
//            String content = getRequestData(request);
//            dto.setContent(content);
//
//            logService.create(dto);
        }
    }
}
